package com.spring.controller.util;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.http.fileupload.DiskFileUpload;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileUploadException;

import com.spring.service.file.IFile;

public class UploadUtil {
	
	protected final static Log logger = LogFactory.getLog(UploadUtil.class);
	
	public static String uploadFileFrom(HttpServletRequest request, String maxBytes, String uploadPath, IFile fileService) {
		logger.info("called upload file");
	
		long maxSize = Long.parseLong(maxBytes);
		
	    List<FileItem> fileItems = null;
	    String jsonToReturn="";
	    
		try {
			DiskFileUpload fu = new DiskFileUpload();
			fu.setSizeMax(-1);
			fileItems = fu.parseRequest(request);
			
			for (Iterator<FileItem> iterator = fileItems.iterator(); iterator.hasNext();) {
				FileItem fi = iterator.next();
				if(!fi.isFormField()) {
					
					final 	String 	name	= fi.getName();
					final 	String 	type 	= fi.getContentType();
					long 	size 	= fi.getSize();
					
					logger.info("found file: NAME["+name+"] SIZE["+size+"bytes] TYPE["+type+"]");
					
			        if(size>0){
				        String filePath = uploadPath+ name;
						File fNew= new File(filePath);
				        try {
							fi.write(fNew);
							logger.info("saved file to: ["+filePath+"]");
							
							//saving thumbnail
							String thumbnailPath = uploadPath +"thumbs/"+name;
							 logger.debug("saving thumbanil  ["+thumbnailPath+"]");
							 createThumbnail(filePath,thumbnailPath);
							 logger.debug("saved thumbanil file with id: ["+thumbnailPath+"]");
							
							int id = fileService.insert(new com.spring.domain.File(){{
								setName(name);
								setType(type);
								//setDescription(description);
							}});
							logger.debug("saved file with id: ["+id+"]");
							
							
							/**
							 * 
							 *  //TODO: implemnetare il json correttamente
							 *  
							 *  [
								  {
								    "name":"picture1.jpg",
								    "size":902604,
								    "url":"\/\/example.org\/files\/picture1.jpg",
								    "thumbnail_url":"\/\/example.org\/thumbnails\/picture1.jpg",
								    "delete_url":"\/\/example.org\/upload-handler?file=picture1.jpg",
								    "delete_type":"DELETE"
								  },
								  {
								    "name":"picture2.jpg",
								    "size":841946,
								    "url":"\/\/example.org\/files\/picture2.jpg",
								    "thumbnail_url":"\/\/example.org\/thumbnails\/picture2.jpg",
								    "delete_url":"\/\/example.org\/upload-handler?file=picture2.jpg",
								    "delete_type":"DELETE"
								  }
								]
							 */
							
							JSONArray array = new JSONArray();
							JSONObject object = new JSONObject();
							object.put("name", name);
							object.put("size", size);
							object.put("url", "../../../../../front/docUpload/"+name);
							object.put("thumbnail_url", "../../../../../front/docUpload/thumbs/"+name);
							array.add(object);
							
							jsonToReturn = array.toString();
							
							//jsonToReturn="[{\"name\":\""+ name + "\",\"size\":\"" + size + "\"}]";
							
						} catch (Exception e) {
							logger.error("error saving file",e);
					
							jsonToReturn="{\"name\":\"erroreeeeeeeeee\",\"type\":\"errrroreeeee\",\"size\":\"errrroeee\"}";
						}
			        }
				}else{
			    	logger.debug("found form fied:"+fi.getFieldName());
			    }
			}
			
		} catch (FileUploadException e1) {
			logger.error("error parsing request in DiskFileUpload max size byte allowed :["+maxSize+"]"+e1.getMessage(),e1);
			jsonToReturn="{\"name\":\"erroreeeeeeeeee tropppo grossso\",\"type\":\"errrroreeeee\",\"size\":\"errrroeee\"}";
		}
		
		return jsonToReturn;
	}
	
	public static List<com.spring.domain.File> deleteFiles(List<com.spring.domain.File> filesList,String uploadPath) throws IllegalArgumentException {
		
		List<com.spring.domain.File> errorDeleted = new ArrayList<com.spring.domain.File>();
		
		logger.debug(">>>>>>>>>> DELETING FILES FROM HD:: "+filesList.toString());
		
		for (Iterator<com.spring.domain.File> iterator = filesList.iterator(); iterator.hasNext();) {
			com.spring.domain.File file =  iterator.next();
			
			try{
				
				String fileName = file.getName();
				
				File f = new File(uploadPath+fileName);
				
				if (!f.exists())
					throw new IllegalArgumentException( "Delete: no such file or directory: " + fileName);

				logger.debug(">>>>>>>>>> FILE : EXIST ");
				
				if (!f.canWrite())
					throw new IllegalArgumentException("Delete: write protected: " + fileName);
				
				logger.debug(">>>>>>>>>> WRITE PERMISSION : OK ");
				
				if (f.isDirectory()) {
					logger.debug(">>>>>>>>>> FILE TYPE : DIRECTORY ");
					String[] files = f.list();
					if (files.length > 0)
						throw new IllegalArgumentException( "Delete: directory not empty: " + fileName);
					
					logger.debug(">>>>>>>>>>>>>>>>>>>> : EMPTY ");
				}
	
				boolean success = f.delete();
	
				if (!success) throw new IllegalArgumentException("Delete: deletion failed");
				
				
				
			}catch(Exception e){
				errorDeleted.add(file);
				logger.debug(">>>>>>>>>>>>>>>>>>>> : #####		ERROR DELETING FILE: "+file+"		#####  :" + e.getMessage() );
			}

		}
		
		return errorDeleted;
	}
	
	
	/*private static BufferedImage resizeImage(BufferedImage originalImage, int type) {
		BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
		Graphics2D g = resizedImage.createGraphics();
		g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
		g.dispose();

		return resizedImage;
	}*/
	
	
	private static BufferedImage resizeImageScaling(BufferedImage originalImage){
		
		AffineTransform tx = new AffineTransform();
		tx.scale(0.3, 0.3);
		//tx.shear(shiftx, shifty);
		//tx.translate(x, y);
		//tx.rotate(radians, originalImage.getWidth()/2, originalImage.getHeight()/2);

		AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
		BufferedImage returnImage = op.filter(originalImage, null);
		return returnImage;
	}
		 
    private static BufferedImage resizeImageWithHint(BufferedImage originalImage, int type){
 
		int MAX_IMG_WIDTH 	= 	300;
		
		int IMG_WIDTH		=	originalImage.getWidth();
		int IMG_HEIGHT		=	originalImage.getHeight();
		
		int calcHeight		= 	0;
		int calcWidth		= 	0;
		
		if( MAX_IMG_WIDTH < IMG_WIDTH ){
			calcWidth = MAX_IMG_WIDTH;
			calcHeight	= (IMG_HEIGHT*MAX_IMG_WIDTH)/IMG_WIDTH;
			/* wOrig : wmax = hOrig: hmax */	
		}
		
		
		BufferedImage resizedImage = new BufferedImage(calcWidth, calcHeight, type);
		Graphics2D g = resizedImage.createGraphics();
		//g.drawImage(originalImage, 0, 0, IMG_WIDTH_FIXED, IMG_HEIGHT_FIXED, null);
		g.drawImage(originalImage, 0, 0, calcWidth, calcHeight, null);
		
		g.setComposite(AlphaComposite.Src);
	 
		g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, 	RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g.setRenderingHint( RenderingHints.KEY_RENDERING, 		RenderingHints.VALUE_RENDER_QUALITY);
		g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, 	RenderingHints.VALUE_ANTIALIAS_ON);
		g.dispose();	
		return resizedImage;
    }	
    
    
    public static void createThumbnail(String pathImgToResize, String thumbnailPathImg ) throws Exception{
		BufferedImage originalImage = ImageIO.read(new File(pathImgToResize));
		int type = originalImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
		
		BufferedImage resizeImageJpg = resizeImageWithHint(originalImage, type);
		//BufferedImage resizeImageJpg = resizeImageScaling(originalImage);
		ImageIO.write(resizeImageJpg, "gif", new File(thumbnailPathImg)); 	
    }
}
